package com.lucaswangdev.logindemo.biz.service.impl;

import com.lucaswangdev.logindemo.biz.manager.UserManager;
import com.lucaswangdev.logindemo.biz.request.user.UserCreateRequest;
import com.lucaswangdev.logindemo.biz.request.user.UserDeleteRequest;
import com.lucaswangdev.logindemo.biz.request.user.UserQueryRequest;
import com.lucaswangdev.logindemo.biz.request.user.UserUpdateRequest;
import com.lucaswangdev.logindemo.biz.response.common.PagingResponse;
import com.lucaswangdev.logindemo.biz.service.UserService;
import com.lucaswangdev.logindemo.constant.common.ErrorConstants;
import com.lucaswangdev.logindemo.exception.BusinessException;
import com.lucaswangdev.logindemo.model.convert.UserConverter;
import com.lucaswangdev.logindemo.model.domain.UserParam;
import com.lucaswangdev.logindemo.model.dto.UserDTO;
import com.lucaswangdev.logindemo.util.ValidatorUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

import static com.lucaswangdev.logindemo.constant.common.UserConstant.USER_LOGIN_STATE;

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserManager userManager;

    /**
     * 盐值，混淆密码
     */
    private static final String SALT = "DEMO";

    @Override
    public Boolean create(UserCreateRequest userCreateRequest) {
        // 参数校验
        String errorMsg = ValidatorUtils.validateAndReturnSingleErrorMsg(userCreateRequest);
        if (StringUtils.isNotBlank(errorMsg)) {
            throw new BusinessException(ErrorConstants.PARAM_ERROR.getErrorCode(), errorMsg);
        }
        // 密码长度太短，错误码要换掉 TODO
        if (userCreateRequest.getEmail().length() < 8 ) {
            throw new BusinessException(ErrorConstants.PARAM_ERROR.getErrorCode(), errorMsg);
        }
        UserParam currentUserParam = new UserParam();
        currentUserParam.setEmail(userCreateRequest.getEmail());
        currentUserParam.setCurrentPage(1);
        currentUserParam.setPageSize(20);
        List<UserDTO> currentUserList = userManager.queryByParam(currentUserParam);
        // 账号重复，错误码要换掉 TODO
        if (currentUserList.size() > 0) {
            throw new BusinessException(ErrorConstants.PARAM_ERROR.getErrorCode(), errorMsg);
        }
        // 2. 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userCreateRequest.getPassword()).getBytes());
        userCreateRequest.setPassword(encryptPassword);
        UserDTO userDTO = UserConverter.INSTANCE.convertRequest2DTO(userCreateRequest);
        userManager.create(userDTO);
        return Boolean.TRUE;
    }

    @Transactional
    @Override
    public UserDTO userLogin(UserCreateRequest userCreateRequest, HttpServletRequest request) {
        // 参数校验
        String errorMsg = ValidatorUtils.validateAndReturnSingleErrorMsg(userCreateRequest);
        if (StringUtils.isNotBlank(errorMsg)) {
            throw new BusinessException(ErrorConstants.PARAM_ERROR.getErrorCode(), errorMsg);
        }
        // 密码长度太短，错误码要换掉 TODO
        if (userCreateRequest.getEmail().length() < 8 ) {
            throw new BusinessException(ErrorConstants.PARAM_ERROR.getErrorCode(), errorMsg);
        }
        // 2. 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userCreateRequest.getPassword()).getBytes());
        UserParam currentUserParam = new UserParam();
        currentUserParam.setEmail(userCreateRequest.getEmail());
        currentUserParam.setPassword(encryptPassword);
        currentUserParam.setCurrentPage(1);
        currentUserParam.setPageSize(20);
        List<UserDTO> currentUserList = userManager.queryByParam(currentUserParam);
        // 用户不存在 TODO
        if (currentUserList.isEmpty()) {
            throw new BusinessException(ErrorConstants.PARAM_ERROR.getErrorCode(), "用户名或密码错误");
        }
        // 3. 记录用户的登录态
        request.getSession().setAttribute(USER_LOGIN_STATE, currentUserList.get(0));
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        return currentUserList.get(0);
    }

    @Override
    public UserDTO getLoginUser(HttpServletRequest request) {
        String sessionId = request.getSession().getId();
        System.out.println("Session ID: " + sessionId);
        System.out.println("Session Attribute (User Login State): " + request.getSession().getAttribute(USER_LOGIN_STATE));

        // 先判断是否已登录
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        UserDTO currentUser = (UserDTO) userObj;
        if (currentUser == null || currentUser.getId() == null) {
            throw new BusinessException("NOT_LOGIN_ERROR", "未登录");
        }
        // 从数据库查询（追求性能的话可以注释，直接走缓存）
        long userId = currentUser.getId();
        UserDTO hasUser = userManager.queryById(userId);
        if (hasUser == null) {
            throw new BusinessException("NOT_LOGIN_ERROR", "未登录");
        }
        return currentUser;
    }

    @Override
    public boolean userLogout(HttpServletRequest request) {
        if (request.getSession().getAttribute(USER_LOGIN_STATE) == null) {
            // TODO
            throw new BusinessException("50001", "未登录");
        }
        // 移除登录态
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return true;
    }

    @Override
    public PagingResponse<UserDTO> listPage(UserQueryRequest queryRequest) {
        // 参数校验
        String errorMsg = ValidatorUtils.validateAndReturnSingleErrorMsg(queryRequest);
        if (StringUtils.isNotBlank(errorMsg)) {
            throw new BusinessException(ErrorConstants.PARAM_ERROR.getErrorCode(), errorMsg);
        }
        UserParam param = new UserParam();
        Integer currentPage;
        Integer pageSize;
        if (queryRequest.getCurrentPage() != null) {
            currentPage = queryRequest.getCurrentPage();
        } else {
            currentPage = 1;
        }
        if (queryRequest.getPageSize() != null) {
            pageSize = queryRequest.getPageSize();
        } else {
            pageSize = 20;
        }
        param.setCurrentPage(currentPage);
        param.setPageSize(pageSize);
        Long count = userManager.countByParam(param);
        if (count == null || count == 0) {
            return PagingResponse.build(Lists.newArrayList(), 0L, queryRequest.getCurrentPage(), queryRequest.getPageSize());
        }
        List<UserDTO> userDTOS = userManager.queryByParam(param);
        return PagingResponse.build(userDTOS, count, queryRequest.getCurrentPage(), queryRequest.getPageSize());
    }

    @Override
    public Boolean modified(UserUpdateRequest userUpdateRequest) {
        // 参数校验
        String errorMsg = ValidatorUtils.validateAndReturnSingleErrorMsg(userUpdateRequest);
        if (StringUtils.isNotBlank(errorMsg)) {
            throw new BusinessException(ErrorConstants.PARAM_ERROR.getErrorCode(), errorMsg);
        }
        UserDTO updateUserDTO = UserConverter.INSTANCE.convertRequest2DTO(userUpdateRequest);
        userManager.update(updateUserDTO);
        return Boolean.TRUE;
    }

    @Override
    public Boolean deleteById(UserDeleteRequest userDeleteRequest) {
        // 参数校验
        String errorMsg = ValidatorUtils.validateAndReturnSingleErrorMsg(userDeleteRequest);
        if (StringUtils.isNotBlank(errorMsg)) {
            throw new BusinessException(ErrorConstants.PARAM_ERROR.getErrorCode(), errorMsg);
        }
        if(userDeleteRequest.getId() != null) {
            userManager.deleteById(userDeleteRequest.getId());
        }
        return Boolean.TRUE;
    }
}
